package com.xlh.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.xlh.dao.UserMessageDetailsMapper;
import com.xlh.dao.UserMessageDetailsMapperExt;
import com.xlh.dao.UserMessageMapper;
import com.xlh.dto.PageDTO;
import com.xlh.dto.UserMessageDTO;
import com.xlh.enums.LocalResourcesEnum;
import com.xlh.param.SendNewMessageParam;
import com.xlh.pojo.UserMessage;
import com.xlh.pojo.UserMessageDetails;
import com.xlh.pojo.UserMessageDetailsExample;
import com.xlh.pojo.UserMessageExample;
import com.xlh.pojo.user.Class;
import com.xlh.service.SendNewMessageService;
import com.xlh.service.SendNewMessageTaskService;
import com.xlh.service.user.ClassService;
import com.xlh.service.user.UserService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author zhr 2019/3/6
 */
@Service
public class SendNewMessageServiceImpl implements SendNewMessageService {

    @Autowired
    private UserService userService;
    @Autowired
    private SendNewMessageTaskService taskService;
    @Autowired
    private ClassService classService;

    @Autowired
    private UserMessageDetailsMapper detailsMapper;
    @Autowired
    private UserMessageDetailsMapperExt detailsMapperExt;
    @Autowired
    private UserMessageMapper messageMapper;

    @Override
    public List<UserMessageDTO> listNewMessage(Long userId) {
        List<UserMessageDTO> result = detailsMapperExt.selectUserMessage(userId, false);
        result.sort(Comparator.comparing(UserMessageDTO::getTime).reversed());
        result.forEach(dto -> dto.setUserPicture(LocalResourcesEnum.SYSTEM_FILE.getMappingUrl(dto.getUserPicture())));
        return result;
    }

    @Override
    public PageDTO<UserMessageDTO> listStudentMessage(Integer pageNum, Integer pageSize, Long id, Long userId) {
        PageHelper.startPage(pageNum, pageSize);

        List<UserMessageDTO> result = detailsMapperExt.selectUserMessage(userId, null);
        result.sort(Comparator.comparing(UserMessageDTO::getTime).reversed());
        result.forEach(dto -> dto.setShow(Objects.equals(id, dto.getId())));
        PageInfo<UserMessageDTO> pageInfo = new PageInfo<>(result);

        taskService.asyncReadMessage(result.stream().map(UserMessageDTO::getId).collect(Collectors.toList()));

        return new PageDTO<>(pageInfo);
    }

    @Override
    public PageDTO<UserMessage> listTeacherMessage(Integer pageNum, Integer pageSize, Long userId) {
        PageHelper.startPage(pageNum, pageSize);

        List<UserMessage> messageList = selectUserMessage(userId);

        PageInfo<UserMessage> pageInfo = new PageInfo<>(messageList);
        return new PageDTO<>(pageInfo);
    }

    @Override
    public void deleteStudentMessage(Long id) {
        detailsMapper.deleteByPrimaryKey(id);
    }

    @Override
    @Transactional
    public void sendNewMessage(Long userId, SendNewMessageParam param) {
        // 发送新消息的逻辑
        List<Long> studentIds = getStudentIds(param.getClassIdList());
        // 新增消息
        UserMessage message = insertNewMessage(userId, param);
        // 新增消息推送关系
        insertUserMessageDetails(message.getId(), studentIds);
        // 使用异步根据用户在线情况发送socket消息
        // 查询详情列表
        List<UserMessageDetails> detailsList = getMessageDetails(message.getId());

        taskService.asyncSendNewMessage(userId, detailsList, param.getContent());
    }

    private void insertUserMessageDetails(Long messageId, List<Long> studentIds) {
        List<UserMessageDetails> list = Lists.newArrayList();
        Long maxId = detailsMapperExt.selectMaxId();
        if (maxId == null) maxId = 0L;

        if (CollectionUtils.isEmpty(studentIds)) return;
        for (Long studentId : studentIds) {
            list.add(new UserMessageDetails(++maxId, messageId, studentId));
        }
        detailsMapperExt.insertBatch(list);
    }

    @Override
    @Transactional
    public void resendMessage(Long userId, Long id, String content) {
        // 查询详情列表
        List<UserMessageDetails> detailsList = getMessageDetails(id);

        // 修改消息
        updateMessage(id, content);
        // 修改消息推送关系为未读
        updateMessageDetails(id);

        // 通过异步给在线用户发送修改的消息
        taskService.asyncSendNewMessage(userId, detailsList, content);
    }

    @Override
    @Transactional
    public void deleteMessage(Long userId, Long id) {
        // 删除消息之前查询出要删除的消息列表
        List<UserMessageDetails> detailsList = getMessageDetails(id);

        // 删除消息
        messageMapper.deleteByPrimaryKey(id);

        // 删除消息推送关系
        deleteMessageDetails(id);

        // 通过异步给在线用户推送删除的消息
        taskService.asyncDeleteMessage(userId, detailsList);
    }

    @Override
    public void changeReadStatus(Long id) {
        UserMessageDetails messageDetails = new UserMessageDetails();
        messageDetails.setId(id);
        messageDetails.setRead(true);
        detailsMapper.updateByPrimaryKeySelective(messageDetails);
    }

    private UserMessage insertNewMessage(Long userId, SendNewMessageParam param) {
        List<String> classes = getClassName(param.getClassIdList());
        UserMessage message = new UserMessage(null, userId, StringUtils.join(classes, ","), param.getContent());
        messageMapper.insertSelective(message);
        return message;
    }

    private List<String> getClassName(List<Long> classIdList) {
        List<Class> classList = classService.listClass(classIdList, null);
        return classList.stream().map(Class::getName).collect(Collectors.toList());
    }

    private List<Long> getStudentIds(List<Long> classIdList) {
        Set<Long> set = Sets.newHashSet();
        for (Long classId : classIdList) {
            List<Long> userIds = userService.getClassUser(classId);
            if (CollectionUtils.isNotEmpty(userIds)) set.addAll(userIds);
        }
        return Lists.newArrayList(set);
    }

    private void updateMessageDetails(Long messageId) {
        UserMessageDetailsExample example = new UserMessageDetailsExample();
        example.createCriteria().andMessageIdEqualTo(messageId);

        UserMessageDetails details = new UserMessageDetails();
        details.setRead(false);
        detailsMapper.updateByExampleSelective(details, example);
    }

    private List<UserMessageDetails> getMessageDetails(Long messageId) {
        UserMessageDetailsExample example = new UserMessageDetailsExample();
        example.createCriteria().andMessageIdEqualTo(messageId);
        return detailsMapper.selectByExample(example);
    }

    private void updateMessage(Long id, String content) {
        UserMessage message = new UserMessage(id, null, null, content);
        messageMapper.updateByPrimaryKeySelective(message);
    }

    private void deleteMessageDetails(Long messageId) {
        UserMessageDetailsExample example = new UserMessageDetailsExample();
        example.createCriteria().andMessageIdEqualTo(messageId);
        detailsMapper.deleteByExample(example);
    }

    /**
     * @param userId 用户id
     * @return 当前用户所有已发布消息，降序排序
     */
    private List<UserMessage> selectUserMessage(Long userId) {
        UserMessageExample example = new UserMessageExample();
        example.setOrderByClause("CREATE_TIME DESC");
        example.createCriteria().andUserIdEqualTo(userId);
        return messageMapper.selectByExample(example);
    }
}
